mod server;
mod database;
pub(crate) mod auth;

use crate::config::auth::AuthConfig;
use crate::config::database::DataSourceConfig;
use anyhow::{anyhow, Context};
use config::{Config, FileFormat};
use serde::Deserialize;
pub use server::ServerConfig;
use std::sync::LazyLock;

static APP_CONFIG: LazyLock<AppConfig> = LazyLock::new(|| AppConfig::load().expect("Failed to initialize config"));
#[derive(Debug, Deserialize)]
pub struct AppConfig {
    server: ServerConfig,
    datasource: DataSourceConfig,
    auth: AuthConfig,
}

impl AppConfig {
    pub fn server(&self) -> &ServerConfig {
        &self.server
    }
    pub fn datasource(&self) -> &DataSourceConfig {
        &self.datasource
    }
    pub fn auth(&self) -> &AuthConfig { &self.auth }
    pub fn load() -> anyhow::Result<Self> {
        Config::builder()
            .add_source(
                config::File::with_name("application")
                    .required(true)
                    .format(FileFormat::Yaml)
            )
            .add_source(
                config::Environment::with_prefix("APP")
                    .try_parsing(true)
                    .separator("_")
                    .list_separator(",")
            ).build()
            .with_context(|| anyhow!("Failed to load config"))?
            .try_deserialize()
            .with_context(|| anyhow!("Failed to load config"))
    }
}

pub fn get() -> &'static AppConfig {
    &APP_CONFIG
}